﻿using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Media;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace fonttest
{
    public class CanvasItem
    {
        public Brush Fill { get; set; }
        public Brush Stroke { get; set; }
        public Geometry Glyph { get; set; }
    }

    public class MainViewModel : INotifyPropertyChanged
    {
        private GlyphTypeface _face;
        private PathGeometry _root;
        private int _index;
        private float _size;
        private bool _pressing = false;

        public MainViewModel(string path, float size)
        {
            _face = new GlyphTypeface(new Uri("file:///" + path));
            _index = -1;
            _size = size;
            CanvasItems = new List<CanvasItem>();
            
            Next();
        }

        public void Prev()
        {
            while (Index > 0)
            {
                Index--;

                if (_root.Figures.Count > 0)
                    break;
            }
        }

        public void Next()
        {
            while (Index < _face.GlyphCount - 1)
            {
                Index++;

                if (_root.Figures.Count > 0)
                    break;
            }
        }

        private bool LoadGlyph(int index)
        {
            if (ValidateIndex(index))
            {
                this.CanvasItems.Clear();
                _root = _face.GetGlyphOutline((ushort)index, _size, _size) as PathGeometry;
                foreach (PathFigure f in _root.Figures)
                {
                    var sub = new PathGeometry(new PathFigure[] { f });
                    sub.Transform = new TranslateTransform(0, _size * _face.XHeight);

                    for (double d = 0.0; d < 1.0; d += 0.1)
                    {
                        Point pt1, pt2;
                        sub.GetPointAtFractionLength(d, out pt1, out pt2);

                        DrawPoint(pt1, Brushes.Red);
                        DrawPoint(pt2, Brushes.Blue);
                    }
                    this.CanvasItems.Add(new CanvasItem() { Fill = Brushes.Gray, Stroke = Brushes.Gray, Glyph = sub });
                }

                NotifyPropertyChanged("CanvasItems");
                return true;
            }

            return false;
        }

        private void Highlight(int fid, Brush brush)
        {
            if (fid < this.CanvasItems.Count)
                this.CanvasItems[fid].Fill = this.CanvasItems[fid].Stroke = brush;
        }

        public bool ValidateIndex(int index)
        {
            return index >= 0 && index < _face.GlyphCount;
        }

        public int Index
        {
            get
            {
                return _index;
            }
            set
            {
                if (LoadGlyph(value))
                {
                    _index = value;
                    NotifyPropertyChanged("Index");
                }
            }
        }

        public List<CanvasItem> CanvasItems { get; set; }

        
        void DrawPoint(Point pt, Brush brush)
        {
            double d = 2;
            var rect = new Rect(new Point(pt.X - d, pt.Y - d), new Point(pt.X + d, pt.Y + d));
            CanvasItems.Add(new CanvasItem() { Stroke = brush, Fill = brush, Glyph = new RectangleGeometry(rect) });
        }

        void NotifyPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        public void MouseDown(Point pt)
        {
            DrawPoint(pt, Brushes.Black);
            NotifyPropertyChanged("CanvasItems");
            _pressing = true;
        }


        public void MouseMove(Point pt, bool pressed)
        {
            if (_pressing)
            {
                if (pressed)
                {
                    DrawPoint(pt, Brushes.Black);
                    NotifyPropertyChanged("CanvasItems");
                }
                else
                {
                    MouseUp(pt);
                }
            }
        }

        public void MouseUp(Point pt)
        {
            DrawPoint(pt, Brushes.Black);
            NotifyPropertyChanged("CanvasItems");
            _pressing = false;
        }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
